#include "Timer.h"

Timer::Timer(void)
{
	__int64 freq = 0;
	// Query high-resolution performance hardware and setup time scaling values
	if (::QueryPerformanceFrequency((LARGE_INTEGER *)&freq)) 
	{ 
		mUsingPerformanceCounter	= true;
		mTimeFreq					= static_cast<timer_t>(freq);
		mTimeScale					= static_cast<timer_t>(1.0) / mTimeFreq;
	} 
	else 
	{ 
		// no performance counter, read in using timeGetTime 
		mUsingPerformanceCounter	= false;
		mTimeFreq					= 1000;
		mTimeScale					= static_cast<timer_t>(0.001);
	}

	Reset();
}

Timer::~Timer(void)
{
}

void Timer::Reset(void)
{	
	// Clear any needed values		
	mFrameRate		= 0;
	mFPSFrameCount	= 0;

	mTimeElapsed	= static_cast<timer_t>(0.0);
	mFPSTimeElapsed	= static_cast<timer_t>(0.0);

	mStopCount	= 0;

	mTimeLast = GetCurrentTick();
	mTimeNow = mTimeStop = mTimeLast;
}

Timer::timer_t Timer::GetCurrentTick (void) const
{
	Timer::timer_t tick = 0;
	if ( mUsingPerformanceCounter ) 
	{
		__int64 counter = 0;
		::QueryPerformanceCounter((LARGE_INTEGER *)&counter);

		tick = counter * mTimeScale;
	} 
	else 
	{		
		tick = ::timeGetTime() * mTimeScale;
	}

	return tick;
}

void Timer::Stop (void)
{
	if (0 == mStopCount )
	{	
		mTimeStop = GetCurrentTick();
	}

	++mStopCount;
}

void Timer::Resume (void)
{
	assert (mStopCount > 0);

	--mStopCount;
	if (mStopCount == 0)
	{
		mTimeNow = GetCurrentTick();

		mTimeLast += mTimeNow - mTimeStop;
		mTimeStop = 0;
	}
}

void Timer::Advance(timer_t timeStep)
{
	if (IsStopped())
	{
		mTimeStop += timeStep;
	}
}

Timer::timer_t Timer::GetTime(void)
{
	mTimeNow = GetCurrentTick();

	Timer::timer_t timeElapsed = 0;
	if (IsStopped())
	{
		timeElapsed = mTimeStop - mTimeLast;
		mFPSTimeElapsed += mTimeNow - mTimeLast;
	}
	else
	{		
		timeElapsed = mTimeNow - mTimeLast;

		mFPSTimeElapsed += timeElapsed;
		mTimeLast = mTimeNow;
	}

	return timeElapsed;
}

Timer::timer_t Timer::Update(Timer::timer_t fLockFPS)
{		
	Timer::timer_t timeElapsed = GetTime();

	if (fLockFPS > 0.0)
	{
		Timer::timer_t FPSTime = 1.0 / fLockFPS;
		while (timeElapsed < FPSTime)
		{		
			timeElapsed = GetTime();
		} 
	}	

	// Calculate Frame Rate
	mFPSFrameCount++;
	mFPSTimeElapsed += timeElapsed;
	if (mFPSTimeElapsed > 1.0) 
	{
		mFrameRate		= mFPSFrameCount;
		mFPSFrameCount	= 0;
		mFPSTimeElapsed	= 0.0;
	}

	mTimeElapsed = timeElapsed;
	return mTimeElapsed;
}
